/* eslint-disable @typescript-eslint/no-unused-expressions */
/**
 * lodop 打印组件封装
 * @returns
 */

import { Col, Empty, Form, Input, Modal, Radio, Row, Select } from 'antd';
import type { ReactNode } from 'react';
import { useEffect, useMemo, useState } from 'react';
import useLodop from './useLodop';
import './print.css';
import { paperSizeOptions } from './const';
import { renderToString } from 'react-dom/server';
import { useDebounceFn } from 'ahooks';

const defaultPaperSize = '210*297';

const LodopPrint = ({
  open,
  onClose,
  printContent,
  previewContent,
  paperSize,
  printer,
  lodopPreview = false,
  storeKey = 'printParams',
}: {
  open?: boolean;
  onClose?: (refresh?: boolean) => void;
  /** 是否进入 lodop 预览 */
  lodopPreview?: boolean;
  /** 需要打印的 节点 */
  printContent?: ReactNode[];
  /** 预览节点 发票有格子，框线样式需要预览，打印就无需了 */
  previewContent?: ReactNode[];
  /** 纸张大小 */
  paperSize?: string;
  /** 打印机 */
  printer?: string;
  /** storeKey 存储打印参数的 key */
  storeKey?: string;
}) => {
  const { printCount, printerList, print } = useLodop();

  const [form] = Form.useForm();

  const [direction, setDirection] = useState('1');

  const [paperSizeDisable, setPaperSizeDisable] = useState(true);

  // 210*297
  const [width, setWidth] = useState('210mm');
  const [height, setHeight] = useState('297mm');

  /** 缩放 */
  const [scale, setScale] = useState('100%');

  /** 边距 */
  const [marginTop, setMarginTop] = useState('0');
  const [marginLeft, setMarginLeft] = useState('0');
  const [marginRight, setMarginRight] = useState('0');
  const [marginBottom, setMarginBottom] = useState('0');

  const onChangePaperSize = (value: string) => {
    if (value === 'customer') {
      setPaperSizeDisable(false);
    } else {
      setPaperSizeDisable(true);
      const paperSize = value
        ?.split('*')
        .map((item: string) => parseFloat(item)) ?? [0, 0];
      setWidth(paperSize[0] + 'mm');
      setHeight(paperSize[1] + 'mm');
      form.setFieldsValue({
        width: paperSize[0],
        height: paperSize[1],
      });
    }
  };

  const onOk = useDebounceFn(
    async () => {
      await form.validateFields();
      const fields = form.getFieldsValue();

      const params = {
        ...fields,
        width: fields.width + 'mm',
        height: fields.height + 'mm',
        lodopPreview,
        printContent: printContent?.map((item) => {
          const str = renderToString(item as any);
          return str;
        }),
      };

      // 存储打印参数到本地
      localStorage.setItem(
        storeKey,
        JSON.stringify({
          ...fields,
          printer: printerList[params.index].label,
          paperSize,
          width: fields.width + 'mm',
          height: fields.height + 'mm',
        }),
      );

      const result = await print(params);

      if (!result) return;

      setTimeout(() => {
        onClose && onClose(true);
      }, 300);
    },
    { wait: 500 },
  );

  const initialValues = useMemo(() => {
    return {
      index: 0,
      direction: '1',
      printPages: '',
      /** A4 */
      paperSize: paperSize ?? defaultPaperSize,
      scale: 100,
      times: 1,
      offset: 'default',
      width: 210,
      height: 297,
      marginTop: 0,
      marginLeft: 0,
      marginRight: 0,
      marginBottom: 0,
    };
  }, [paperSize]);

  useEffect(() => {
    if (!open) return;
    const params = localStorage.getItem(storeKey);
    if (!params && paperSize) {
      const w = paperSize.split('*')[0];
      const h = paperSize.split('*')[1];
      setWidth(w + 'mm');
      setHeight(h + 'mm');
      form.setFieldsValue({
        paperSize,
        width: parseInt(w),
        height: parseInt(h),
      });
      setPaperSizeDisable(true);
    }
  }, [open, form, paperSize, storeKey]);

  useEffect(() => {
    if (!open) return;
    const params = localStorage.getItem(storeKey);
    if (!params && printer) {
      const index = printerList.findIndex((item) => item.label === printer);
      index > -1 &&
        form.setFieldsValue({
          index,
        });
    }
  }, [open, form, printerList, printer, storeKey]);

  useEffect(() => {
    if (open) {
      const params = localStorage.getItem(storeKey);
      if (!params) return;
      try {
        const paramsObj = JSON.parse(params);

        const index = printerList.findIndex(
          (item) => item.label === paramsObj.printer,
        );

        form.setFieldsValue({
          ...paramsObj,
          width: parseFloat(paramsObj.width),
          height: parseFloat(paramsObj.height),
          index: index > -1 ? index : 0,
        });
        setWidth(paramsObj.width);
        setHeight(paramsObj.height);
        setMarginTop(paramsObj.marginTop + 'mm');
        setMarginBottom(paramsObj.marginBottom + 'mm');
        setMarginLeft(paramsObj.marginLeft + 'mm');
        setMarginRight(paramsObj.marginRight + 'mm');
        setScale(paramsObj.scale + '%');
        setDirection(paramsObj.direction);
        paperSize ? setPaperSizeDisable(true) : setPaperSizeDisable(false);
      } catch (error) {
        console.log('error: ', error);
      }
    }
  }, [open, form, printerList, storeKey, paperSize]);

  return (
    <Modal
      title={'打印预览'}
      open={open}
      okText="打印"
      width={'100%'}
      destroyOnClose
      style={{
        margin: 0,
        top: 0,
        maxWidth: '100%',
        height: '100vh',
      }}
      styles={{
        content: {
          width: '100%',
          height: '100vh',
        },
        body: {
          height: 'calc(100% - 24px - 46px)',
        },
      }}
      cancelText="取消打印"
      onCancel={() => {
        onClose && onClose();
      }}
      onOk={onOk.run}
    >
      <div className="print-content">
        <div className="print-control">
          <Form layout="vertical" form={form} initialValues={initialValues}>
            <Form.Item label={`打印机 (${printCount})`} name="index">
              <Select placeholder="请选择打印机" options={printerList} />
            </Form.Item>
            <Form.Item label="布局" name="direction">
              <Radio.Group
                disabled={!!paperSize}
                onChange={(e) => {
                  setDirection(e.target.value);
                }}
              >
                <Radio value={'1'}>横向</Radio>
                <Radio value={'2'}>纵向</Radio>
              </Radio.Group>
            </Form.Item>
            <Form.Item label="页面" name="printPages">
              <Input placeholder="全部" />
            </Form.Item>
            <Form.Item label="纸张大小" name="paperSize">
              <Select
                placeholder="请选择纸张大小"
                disabled={!!paperSize}
                options={paperSizeOptions}
                onChange={onChangePaperSize}
              />
            </Form.Item>
            <Row gutter={12}>
              <Col span={12}>
                <Form.Item label="纸张宽度" name="width">
                  <Input
                    suffix="mm"
                    disabled={paperSizeDisable || !!paperSize}
                  />
                </Form.Item>
              </Col>
              <Col span={12}>
                <Form.Item label="纸张高度" name="height">
                  <Input
                    suffix="mm"
                    disabled={paperSizeDisable || !!paperSize}
                  />
                </Form.Item>
              </Col>
            </Row>

            <Form.Item label="缩放" name="scale">
              <Input
                type="number"
                suffix="%"
                disabled={!!paperSize}
                onChange={(e) => {
                  const value = e.target.value ? e.target.value + '%' : '100%';
                  setScale(value);
                }}
              />
            </Form.Item>
            <Form.Item
              label="每张纸打印的页数"
              name="times"
              rules={[
                {
                  validator(_, value) {
                    if (value < 1) {
                      return Promise.reject('每张打印页数必须大于等于1');
                    }
                    return Promise.resolve();
                  },
                },
              ]}
            >
              <Input type="number" />
            </Form.Item>
            <div style={{ marginBottom: 12 }}>边距</div>
            <Row gutter={12}>
              <Col span={12}>
                <Form.Item
                  label="顶部"
                  name="marginTop"
                  rules={[
                    {
                      validator(_, value) {
                        if (value < 0) {
                          return Promise.reject('边距必须大于等于0');
                        }
                        return Promise.resolve();
                      },
                    },
                  ]}
                >
                  <Input
                    type="number"
                    suffix="mm"
                    disabled={!!paperSize}
                    onChange={(e) => {
                      const value = e.target.value ? e.target.value + 'mm' : '';
                      setMarginTop(value);
                    }}
                  />
                </Form.Item>
              </Col>
              <Col span={12}>
                <Form.Item
                  label="底部"
                  name="marginBottom"
                  rules={[
                    {
                      validator(_, value) {
                        if (value < 0) {
                          return Promise.reject('边距必须大于等于0');
                        }
                        return Promise.resolve();
                      },
                    },
                  ]}
                >
                  <Input
                    type="number"
                    suffix="mm"
                    disabled={!!paperSize}
                    onChange={(e) => {
                      const value = e.target.value ? e.target.value + 'mm' : '';
                      setMarginBottom(value);
                    }}
                  />
                </Form.Item>
              </Col>
            </Row>
            <Row gutter={12}>
              <Col span={12}>
                <Form.Item
                  label="左"
                  name="marginLeft"
                  rules={[
                    {
                      validator(_, value) {
                        if (value < 0) {
                          return Promise.reject('边距必须大于等于0');
                        }
                        return Promise.resolve();
                      },
                    },
                  ]}
                >
                  <Input
                    type="number"
                    suffix="mm"
                    disabled={!!paperSize}
                    onChange={(e) => {
                      const value = e.target.value ? e.target.value + 'mm' : '';
                      setMarginLeft(value);
                    }}
                  />
                </Form.Item>
              </Col>
              <Col span={12}>
                <Form.Item
                  label="右"
                  name="marginRight"
                  rules={[
                    {
                      validator(_, value) {
                        if (value < 0) {
                          return Promise.reject('边距必须大于等于0');
                        }
                        return Promise.resolve();
                      },
                    },
                  ]}
                >
                  <Input
                    type="number"
                    suffix="mm"
                    disabled={!!paperSize}
                    onChange={(e) => {
                      const value = e.target.value ? e.target.value + 'mm' : '';
                      setMarginRight(value);
                    }}
                  />
                </Form.Item>
              </Col>
            </Row>
          </Form>
        </div>
        <div className="print-preview">
          {/* 更换为虚拟列表 */}
          {previewContent && previewContent.length > 0 ? (
            previewContent?.map((node, index) => {
              return (
                <div
                  className="print-page"
                  key={index}
                  style={{
                    width: direction === '1' ? width : height,
                    maxWidth: direction === '1' ? width : height,
                    height: direction === '1' ? height : width,
                    maxHeight: direction === '1' ? height : width,
                    marginBottom:
                      index === previewContent.length - 1 ? '0' : '12px',
                  }}
                >
                  <div
                    className="print-page-inner"
                    style={{
                      padding: `${marginTop} ${marginRight} ${marginBottom} ${marginLeft}`,
                      height:
                        marginTop && marginBottom
                          ? `calc(100% - ${marginTop} - ${marginBottom})`
                          : marginTop
                          ? `calc(100% - ${marginTop})`
                          : marginBottom
                          ? `calc(100% - ${marginBottom})`
                          : '',
                    }}
                  >
                    <div
                      style={{
                        transform: `scale(${scale})`,
                        transformOrigin: '0 0',
                        height: '100%',
                      }}
                    >
                      {node}
                    </div>
                  </div>
                </div>
              );
            })
          ) : (
            <Empty description="暂无预览内容" />
          )}
        </div>
      </div>
    </Modal>
  );
};

export default LodopPrint;
